/**
 * Copyright (c) 2011-2020, hubin (jobob@qq.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package cn.wp.common.core.web.interceptor;

import cn.hutool.core.util.StrUtil;
import cn.wp.common.core.Wp;
import cn.wp.common.core.WpVar;
import cn.wp.common.core.authentication.AuthenticationContext;
import cn.wp.common.core.authentication.AuthenticationInfo;
import cn.wp.common.core.authentication.util.TokenUtil;
import cn.wp.common.core.dto.WpResult;
import cn.wp.common.core.exception.WpException;
import cn.wp.common.core.util.ResponseUtil;
import cn.wp.common.core.web.WpUserContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.method.HandlerMethod;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Method;
import java.net.URLDecoder;

/**
 * 登陆认证
 * Created by chenyb on 2019-09-24
 */
public class LoginInterceptor extends WpAbstractInterceptor {

    private static final Logger logger = LoggerFactory.getLogger(LoginInterceptor.class);

    public LoginInterceptor(String[] pathPatterns, String[] ignores) {
        super(pathPatterns, ignores);
    }

    /**
     * 登录权限验证
     * 方法拦截 controller 处理之前进行调用。
     */
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler){
        /**
         * 处理 controller 方法
         * <p>
         * 判断 handler 是否为 HandlerMethod 实例
         * </p>
         */
        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            Method method = handlerMethod.getMethod();
            String tokenErrMsg = "无效Token";
            String userErrMsg = "未登录，访问受限";

            String tokenName = Wp.self().getAuthenticationProperties().getTokenName();
            // 从请求头获取token
            String token = request.getHeader(tokenName);

            // 未获取到尝试从cookie中获取
            if(StrUtil.isBlank(token)){
                Cookie[] cookies = request.getCookies();
                if(cookies != null) {
                    for (Cookie cookie : cookies) {
                        if (tokenName.equals(cookie.getName())) {
                            token = cookie.getValue();
                            break;
                        }
                    }
                }
            }

            // 未获取到尝试从参数中获取
            if(StrUtil.isBlank(token)){
                token = request.getParameter(tokenName);
            }

            // 判断是否为超级token
            if(WpVar.SUPER_TOKEN_VALUE.equals(token)){
                AuthenticationInfo authenticationInfo = new AuthenticationInfo();
                authenticationInfo.setId("super-user-id");
                WpUserContext.set(authenticationInfo);
                request.setAttribute(WpVar.TOKEN_ID_KEY,WpVar.SUPER_TOKEN_ID);
                request.setAttribute(WpVar.TOKEN_VALUE_KEY,token);
                logger.info("token check: [" + request.getRequestURL() + "] use super token");
                return true;
            }

            // token校验
            String tokenId = TokenUtil.self().parseToken(token);
            if(tokenId == null){
                WpResult wpResult = new WpResult();
                wpResult.failure(WpVar.TOKEN_INVALID_CODE, tokenErrMsg);
                ResponseUtil.writeJson(response,wpResult);
                return false;
            }

            // token值ID设置到request
            request.setAttribute(WpVar.TOKEN_ID_KEY,tokenId);
            // token原始值放入request
            request.setAttribute(WpVar.TOKEN_VALUE_KEY,token);

            AuthenticationInfo authenticationInfo = AuthenticationContext.self().currentUser();
            if(authenticationInfo ==  null){
                WpResult wpResult = new WpResult();
                wpResult.failure(WpVar.NO_LOGIN_CODE, userErrMsg);
                ResponseUtil.writeJson(response,wpResult);
                return false;
            }
            WpUserContext.set(authenticationInfo);

            /*AuthenticationInfo authenticationInfo = SSOAuthentication.getAuthenticationInfo();
            if (authenticationInfo == null) {
                if (HttpUtil.isAjax(request)) {
                    *//*
                     * Handler 处理 AJAX 请求
					 *//*
                    response.setCharacterEncoding(AoomsVar.ENCODE);
                    DataResult dataResult = new DataResult();
                    dataResult.failure(HttpStatus.HTTP_UNAUTHORIZED, errMsg);
                    try{
                        response.getWriter().write(dataResult.toJsonStr());
                        response.getWriter().flush();
                    }catch (IOException e){
                        throw AoomsExceptions.create(e.getMessage(),e);
                    }
                    return false;
                } else {
					*//*
					 * token 为空，调用 Handler 处理
					 * 返回 true 继续执行，清理登录状态并重定向至登录界面
					 *//*
					logger.info(errMsg);
                    try {
                        SSOHelper.clearRedirectLogin(request, response);
                    } catch (IOException e){
                        throw AoomsExceptions.create(e.getMessage(),e);
                    }
                    return false;
                }
            }*/
        }

        /**
         * 通过拦截
         */
        return true;
    }

    @Override
    public void finalHandle(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) {
        WpUserContext.remove();
    }

}
